home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / LIB / GLUT / glut_vidresize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  6.7 KB  |  231 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1996. */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. #include <stdlib.h>
  9.  
  10. #if !defined(_WIN32)
  11. #include <GL/glx.h>
  12. #endif
  13.  
  14. #ifdef __sgi
  15. #include <dlfcn.h>
  16. #endif
  17.  
  18. #include "glutint.h"
  19.  
  20. /* Grumble.  The IRIX 6.3 and early IRIX 6.4 OpenGL headers
  21.    support the video resize extension, but failed to define
  22.    GLX_SGIX_video_resize. */
  23. #ifdef GLX_SYNC_FRAME_SGIX
  24. #define GLX_SGIX_video_resize 1
  25. #endif
  26.  
  27. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  28. static int canVideoResize = -1;
  29. static int videoResizeChannel;
  30. #else
  31. static int canVideoResize = 0;
  32. #endif
  33. static int videoResizeInUse = 0;
  34. static int dx = -1, dy = -1, dw = -1, dh = -1;
  35.  
  36. /* XXX Note that IRIX 6.2, 6.3, and some 6.4 versions have a
  37.    bug where programs seg-fault when they attempt video
  38.    resizing from an indirect OpenGL context (either local or
  39.    over a network). */
  40.  
  41. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  42.  
  43. static volatile int errorCaught;
  44.  
  45. /* ARGSUSED */
  46. static
  47. catchXSGIvcErrors(Display * dpy, XErrorEvent * event)
  48. {
  49.   errorCaught = 1;
  50.   return 0;
  51. }
  52. #endif
  53.  
  54. /* CENTRY */
  55. int APIENTRY 
  56. glutVideoResizeGet(GLenum param)
  57. {
  58. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  59.   if (canVideoResize < 0) {
  60.     canVideoResize = __glutIsSupportedByGLX("GLX_SGIX_video_resize");
  61.     if (canVideoResize) {
  62. #if __sgi
  63.       /* This is a hack because IRIX 6.2, 6.3, and some 6.4
  64.          versions were released with GLX_SGIX_video_resize
  65.          being advertised by the X server though the video
  66.          resize extension is not actually supported.  We try to
  67.          determine if the libGL.so we are using actually has a
  68.          video resize entrypoint before we try to use the
  69.          feature. */
  70.       void (*func) (void);
  71.       void *glxDso = dlopen("libGL.so", RTLD_LAZY);
  72.  
  73.       func = (void (*)(void)) dlsym(glxDso, "glXQueryChannelDeltasSGIX");
  74.       if (!func) {
  75.         canVideoResize = 0;
  76.       } else
  77. #endif
  78.       {
  79.         char *channelString;
  80.         int (*handler) (Display *, XErrorEvent *);
  81.  
  82.         channelString = getenv("GLUT_VIDEO_RESIZE_CHANNEL");
  83.         videoResizeChannel = channelString ? atoi(channelString) : 0;
  84.  
  85.         /* Work around another annoying problem with SGI's
  86.            GLX_SGIX_video_resize implementation.  Early IRIX
  87.            6.4 OpenGL's advertise the extension and have the
  88.            video resize API, but an XSGIvc X protocol errors
  89.            result trying to use the API.  Set up an error
  90.            handler to intercept what would otherwise be a fatal
  91.            error.  If an error was recieved, do not report that
  92.            video resize is possible. */
  93.         handler = XSetErrorHandler(catchXSGIvcErrors);
  94.  
  95.         errorCaught = 0;
  96.  
  97.         glXQueryChannelDeltasSGIX(__glutDisplay, __glutScreen,
  98.           videoResizeChannel, &dx, &dy, &dw, &dh);
  99.  
  100.         /* glXQueryChannelDeltasSGIX is an inherent X server
  101.            round-trip so we know we will have gotten either the
  102.            correct reply or and error by this time. */
  103.         XSetErrorHandler(handler);
  104.  
  105.         /* Still yet another work around.  In IRIX 6.4 betas,
  106.            glXQueryChannelDeltasSGIX will return as if it
  107.            succeeded, but the values are filled with junk.
  108.            Watch to make sure the delta variables really make
  109.            sense. */
  110.         if (errorCaught ||
  111.           dx < 0 || dy < 0 || dw < 0 || dh < 0 ||
  112.           dx > 2048 || dy > 2048 || dw > 2048 || dh > 2048) {
  113.           canVideoResize = 0;
  114.         }
  115.       }
  116.     }
  117.   }
  118. #endif /* GLX_SGIX_video_resize */
  119.  
  120.   switch (param) {
  121.   case GLUT_VIDEO_RESIZE_POSSIBLE:
  122.     return canVideoResize;
  123.   case GLUT_VIDEO_RESIZE_IN_USE:
  124.     return videoResizeInUse;
  125.   case GLUT_VIDEO_RESIZE_X_DELTA:
  126.     return dx;
  127.   case GLUT_VIDEO_RESIZE_Y_DELTA:
  128.     return dy;
  129.   case GLUT_VIDEO_RESIZE_WIDTH_DELTA:
  130.     return dw;
  131.   case GLUT_VIDEO_RESIZE_HEIGHT_DELTA:
  132.     return dh;
  133.   case GLUT_VIDEO_RESIZE_X:
  134.   case GLUT_VIDEO_RESIZE_Y:
  135.   case GLUT_VIDEO_RESIZE_WIDTH:
  136.   case GLUT_VIDEO_RESIZE_HEIGHT:
  137. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  138.     if (videoResizeInUse) {
  139.       int x, y, width, height;
  140.  
  141.       glXQueryChannelRectSGIX(__glutDisplay, __glutScreen,
  142.         videoResizeChannel, &x, &y, &width, &height);
  143.       switch (param) {
  144.       case GLUT_VIDEO_RESIZE_X:
  145.         return x;
  146.       case GLUT_VIDEO_RESIZE_Y:
  147.         return y;
  148.       case GLUT_VIDEO_RESIZE_WIDTH:
  149.         return width;
  150.       case GLUT_VIDEO_RESIZE_HEIGHT:
  151.         return height;
  152.       }
  153.     }
  154. #endif
  155.     return -1;
  156.   default:
  157.     __glutWarning("invalid glutVideoResizeGet parameter: %d", param);
  158.     return -1;
  159.   }
  160. }
  161.  
  162. void APIENTRY 
  163. glutSetupVideoResizing(void)
  164. {
  165. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  166.   if (glutVideoResizeGet(GLUT_VIDEO_RESIZE_POSSIBLE)) {
  167.     glXBindChannelToWindowSGIX(__glutDisplay, __glutScreen,
  168.       videoResizeChannel, __glutCurrentWindow->win);
  169.     videoResizeInUse = 1;
  170.   } else
  171. #endif
  172.     __glutFatalError("glutEstablishVideoResizing: video resizing not possible.\n");
  173. }
  174.  
  175. void APIENTRY 
  176. glutStopVideoResizing(void)
  177. {
  178. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  179.   if (glutVideoResizeGet(GLUT_VIDEO_RESIZE_POSSIBLE)) {
  180.     if (videoResizeInUse) {
  181.       glXBindChannelToWindowSGIX(__glutDisplay, __glutScreen,
  182.         videoResizeChannel, None);
  183.       videoResizeInUse = 0;
  184.     }
  185.   }
  186. #endif
  187. }
  188.  
  189. /* ARGSUSED */
  190. void APIENTRY 
  191. glutVideoResize(int x, int y, int width, int height)
  192. {
  193. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  194.   if (videoResizeInUse) {
  195. #ifdef GLX_SYNC_SWAP_SGIX
  196.     /* glXChannelRectSyncSGIX introduced in a patch to IRIX
  197.        6.2; the original unpatched IRIX 6.2 behavior is always
  198.        GLX_SYNC_SWAP_SGIX. */
  199.     glXChannelRectSyncSGIX(__glutDisplay, __glutScreen,
  200.       videoResizeChannel, GLX_SYNC_SWAP_SGIX);
  201. #endif
  202.     glXChannelRectSGIX(__glutDisplay, __glutScreen,
  203.       videoResizeChannel, x, y, width, height);
  204.   }
  205. #endif
  206. }
  207.  
  208. /* ARGSUSED */
  209. void APIENTRY 
  210. glutVideoPan(int x, int y, int width, int height)
  211. {
  212. #if defined(GLX_VERSION_1_1) && defined(GLX_SGIX_video_resize)
  213.   if (videoResizeInUse) {
  214. #ifdef GLX_SYNC_FRAME_SGIX
  215.     /* glXChannelRectSyncSGIX introduced in a patch to IRIX
  216.        6.2; the original unpatched IRIX 6.2 behavior is always
  217.        GLX_SYNC_SWAP_SGIX.  We just ignore that we cannot
  218.        accomplish GLX_SYNC_FRAME_SGIX on IRIX unpatched 6.2;
  219.        this means you'd need a glutSwapBuffers to actually
  220.        realize the video resize. */
  221.     glXChannelRectSyncSGIX(__glutDisplay, __glutScreen,
  222.       videoResizeChannel, GLX_SYNC_FRAME_SGIX);
  223. #endif
  224.     glXChannelRectSGIX(__glutDisplay, __glutScreen,
  225.       videoResizeChannel, x, y, width, height);
  226.   }
  227. #endif
  228. }
  229.  
  230. /* ENDCENTRY */
  231.